<?php

namespace App\Services\System;
use App\Beans\TreeSelect;
use App\Models\System\SysDeptModel;
use App\Models\System\SysRoleModel;
use App\Validate\System\SysDeptValidate;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Auth;
use App\Common\Constants\UserConst;

/**
* 部门表 逻辑层 前端API业务分装
* @create 2023-09-13 11:30:11
*/
class SysDeptService {

    private SysDeptModel $sysDeptModel;
    private SysRoleModel $sysRoleModel;

    public function __construct(SysDeptModel $sysDeptModel, SysRoleModel $sysRoleModel) {
        $this->sysDeptModel = $sysDeptModel;
        $this->sysRoleModel = $sysRoleModel;
    }

    /**
     * 查询部门管理数据
     * 
     * @param $dept 部门信息
     * @return Collection|SysDeptModel[] 部门信息集合
     */
    public function selectDeptList(SysDeptModel $dept): Collection {
        return $this->sysDeptModel->selectDeptList($dept->toArray());
    }
    
    /**
     * 查询部门树结构信息
     * 
     * @param $dept 部门信息
     * @return array|TreeSelect[] 部门树信息集合
     */
    public function selectDeptTreeList(SysDeptModel $dept): array {
        $depts = $this->selectDeptList($dept);
        return $this->buildDeptTreeSelect($depts);
    }

    /**
     * 构建前端所需要树结构
     * 
     * @param Collection|SysDeptModel[] $depts 部门列表
     * @return array 树结构列表
     */
    public function buildDeptTree(Collection $depts): array {
        $returnList = [];
        $topids = $depts->pluck('dept_id');
        $depts->each(function($dept) use($topids, $depts) {
            if (!$topids->contains($dept->parent_id)) {
                $this->recursionFn($depts, $dept);
                $returnList[] = $dept;
            }
        });
        return empty($returnList) ? $depts->toArray() : $returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     * 
     * @param Collection|SysDeptModel[] $depts 部门列表
     * @return array|TreeSelect[] 下拉树结构列表
     */
    public function buildDeptTreeSelect(Collection $depts): array {
        $deptTrees = $this->buildDeptTree($depts);
        return array_map(fn($it) => new TreeSelect($it), $deptTrees);
    }

    /**
     * 根据角色ID查询部门树信息
     * 
     * @param $roleId 角色ID
     * @return array|int[] 选中部门列表
     */
    public function selectDeptListByRoleId(int $roleId): array {
        $role = $this->sysRoleModel->selectByRoleId($roleId);
        return $this->sysDeptModel->selectDeptListByRoleId($roleId, $role->isDeptCheckStrictly);
    }

    /**
     * 根据部门ID查询信息
     * 
     * @param int $deptId 部门ID
     * @return 部门信息
     */
    public function selectDeptById(int $deptId): SysDeptModel {
        return $this->sysDeptModel->selectDeptById($deptId);
    }

    /**
     * 根据ID查询所有子部门（正常状态）
     * 
     * @param $deptId 部门ID
     * @return 子部门数
     */
    public function selectNormalChildrenDeptById(int $deptId): int {
        return $this->sysDeptModel->selectNormalChildrenDeptById($deptId);
    }

    /**
     * 是否存在子节点
     * 
     * @param $deptId 部门ID
     * @return 结果
     */
    public function hasChildByDeptId(int $deptId): bool {
        $result = $this->sysDeptModel->hasChildByDeptId($deptId);
        return $result > 0;
    }

    /**
     * 查询部门是否存在用户
     * 
     * @param $deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    public function checkDeptExistUser(int $deptId): bool {
        $result = $this->sysDeptModel->checkDeptExistUser($deptId);
        return $result > 0;
    }

    /**
     * 校验部门名称是否唯一
     * 
     * @param $dept 部门信息
     * @return 结果
     */
    public function checkDeptNameUnique(SysDeptModel $dept): string {
        $deptId = $dept->dept_id;
        $info = $this->sysDeptModel->checkDeptNameUnique($dept->dept_name, $dept->parent_id);
        if ($info && $info->dept_id != $dept->dept_id) {
            return UserConst::NOT_UNIQUE();
        }
        return UserConst::UNIQUE();
    }

    /**
     * 校验部门是否有数据权限
     * 
     * @param $deptId 部门id
     */
    public function checkDeptDataScope(int $deptId): void {
        if (!user()->isAdmin()) {
            $depts = $this->sysDeptModel->selectDeptList(['deptId' => $deptId]);
            if (!$depts) {
                throw_str('没有权限访问部门数据！');
            }
        }
    }

    /**
     * 新增保存部门信息
     * 
     * @param array|SysDeptModel $dept 部门信息
     * @return SysDeptModel 结果
     */
    public function insertDept(array $dept): SysDeptModel {
        $model = $this->sysDeptModel->selectDeptById($dept['parentId']);
        if (UserConst::DEPT_NORMAL() != $dept->status) {
            throw_str('部门停用，不允许新增');
        }
        $dept['ancestors'] = $model->ancestors .','. $dept['parentId'];
        return $this->sysDeptModel->insertDept($dept);
    }

    /**
     * 修改保存部门信息
     * 
     * @param array|SysDeptModel $dept 部门信息
     * @return int 结果
     */
    public function updateDept(array $dept): int {
        $newParentDept = $this->sysDeptModel->selectDeptById($dept['parentId']);
        $oldDept = $this->sysDeptModel->selectDeptById($dept['deptId']);
        if ($newParentDept && $oldDept) {
            $newAncestors = $newParentDept->ancestors .','. $newParentDept->dept_id;
            $oldAncestors = $oldDept->ancestors;
            $dept['ancestors'] = $newAncestors;
            $this->updateDeptChildren($dept['deptId'], $newAncestors, $oldAncestors);
        }
        $result = $this->sysDeptModel->updateDept($dept);
        if (UserConst::DEPT_NORMAL() == $dept['status'] && !empty($dept['ancestors'])) {
            $this->updateParentDeptStatusNormal($dept);
        }
        return $result;
    }

    /**
     * 修改该部门的父级部门状态
     * 
     * @param array|SysDeptModel dept 当前部门
     */
    private function updateParentDeptStatusNormal(array $dept): void {
        $this->sysDeptModel->updateDeptStatusNormal(explode(',', $dept['ancestors']));
    }

    /**
     * 修改子元素关系
     * 
     * @param int $deptId 被修改的部门ID
     * @param string $newAncestors 新的父ID集合
     * @param string $oldAncestors 旧的父ID集合
     */
    public function updateDeptChildren(int $deptId, string $newAncestors, string $oldAncestors): void {
        $children = $this->sysDeptModel->selectChildrenDeptById($deptId);
        foreach ($children as &$child) {
            $child->ancestors = preg_replace("/{$oldAncestors}/", $newAncestors, $child['ancestors'], 1);
        }
        if (!empty($children)) {
            $this->sysDeptModel->updateDeptChildren($children);
        }
    }

    /**
     * 删除部门管理信息
     * 
     * @param $deptId 部门ID
     * @return int 结果
     */
    public function deleteDeptById(int $deptId): int {
        return $this->sysDeptModel->deleteDeptById($deptId);
    }

    /**
     * 递归列表
     * @param array|SysDeptModel[]|Collection $list
     * @param array|SysDeptModel $t
     */
    private function recursionFn(Collection $list, SysDeptModel $t) {
        // 得到子节点列表
        $childList = $this->getChildList($list, $t);
        $t->children = $childList;
        $childList->each(function ($child) use ($list) {
            if ($this->hasChild($list, $child)) {
                $this->recursionFn($list, $child);
            }
        });
    }

    /**
     * 得到子节点列表
     * @param Collection|SysDeptModel[] $list
     * @param Collection|SysDeptModel $t
     * @return Collection|SysDeptModel[]
     */
    private function getChildList(Collection $list, SysDeptModel $t): Collection {
        $tlist = collect();
        $list->filter(fn($it)=>!empty($it['parent_id']) && $it['parent_id'] == $t->dept_id)->each(function($it) use($tlist) {
            $tlist->push($it);
        });
        //     if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue())
        return $tlist;
    }

    /**
     * 判断是否有子节点
     */
    private function hasChild(Collection $list, SysDeptModel $t): bool {
        return $this->getChildList($list, $t)->isNotEmpty();
    }

}
